/* * Sun Public License Notice * * The contents of this file are subject to the Sun Public License * Version 1.0 (the "License"). You may not use this file except in * compliance with the License. A copy of the License is available at * http://www.sun.com/ * * The Original Code is NetBeans. The Initial Developer of the Original * Code is Sun Microsystems, Inc. Portions Copyright 1997-2000 Sun * Microsystems, Inc. All Rights Reserved. */ package org.netbeans.modules.jarpackager.util; import java.util.*; import java.util.jar.*; import java.io.File; import java.io.IOException; import java.awt.Component; import java.awt.Dimension; import java.awt.Rectangle; import java.beans.PropertyVetoException; import org.openide.util.actions.NodeAction; import org.openide.util.NbBundle; import org.openide.util.HelpCtx; import org.openide.nodes.Node; import org.openide.loaders.DataObject; import org.openide.loaders.MultiDataObject; import org.openide.loaders.DataFolder; import org.openide.filesystems.FileObject; import org.openide.TopManager; import org.openide.filesystems.*; import org.openide.execution.NbClassPath; import org.netbeans.modules.jarpackager.JarContent; import org.netbeans.modules.jarpackager.*; /** Static utilities used for common purposes by other classes. * * @author Dafe Simonek */ public final class JarUtils extends Object { static final String MANIFEST_VERSION = "1.0"; // NOI18N /** No need to instantiate */ private JarUtils () { } /** @return true if specified nodes all can be added to the * archive described by given jar content. */ public static boolean canAdd (JarContent jc, Node[] nodes, String targetName) { if ((nodes.length == 0) || (jc == null)) { return false; } // check compatibility of selected nodes Node parent = null; for (int i = 0; i < nodes.length; i++) { parent = nodes[i].getParentNode(); if ((parent != null) && (parent.getCookie(DataFolder.class) == null) && (nodes[i].getCookie(DataFolder.class) == null)) { return false; } } // check if it is not part of itself DataObject curDo = null; DataFolder curFolder = null; File targetFile = (targetName == null) ? null : new File(targetName); FileSystem curFs = null; for (int i = 0; i < nodes.length; i++) { curDo = (DataObject)nodes[i].getCookie(DataObject.class); if (curDo != null) { // check if processed item is not archive itself if ((curDo instanceof JarDataObject) && isEqual(targetFile, NbClassPath.toFile(curDo.getPrimaryFile()))) { return false; } // check if processed item is not from the filesystem of the // archive itself try { curFs = curDo.getPrimaryFile().getFileSystem(); } catch (FileStateInvalidException exc) { // file system in invalid state, so does not allow // to add itema to archive from such file system return false; } if ((curFs instanceof JarFileSystem) && isEqual(targetFile, ((JarFileSystem)curFs).getJarFile())) { return false; } } } return true; } /** Helper, returns true if given files are the same * (their extension can be different) */ private static boolean isEqual (File file1, File file2) { // deal with nulls if (file1 == null) { return (file2 == null) ? true : false; } if (file2 == null) { return (file1 == null) ? true : false; } String name1 = file1.getPath(); String name2 = file2.getPath(); // strip the extensions int index1 = name1.lastIndexOf('.'); if (index1 < 0) { index1 = name1.length(); } int index2 = name2.lastIndexOf('.'); if (index2 < 0) { index2 = name2.length(); } return new File(name1.substring(0, index1)).equals( new File(name2.substring(0, index2))); } /** Adds list of file objects representing all primary and * secondary entries of data objects which are represented by * specified nodes. * @param jc jar content to which we want to add created file list */ public static void addFileList (JarContent jc, Node[] nodes) { // transform nodes to collection of file objects ArrayList result = new ArrayList(nodes.length * 2); DataObject curDo = null; for (int i = 0; i < nodes.length; i++) { curDo = (DataObject)nodes[i].getCookie(DataObject.class); if (curDo != null) { // add only primary file object result.add(curDo.getPrimaryFile()); } } // add to the jar content jc.putFiles(result); } /** Removes list of file objects representing all primary and * secondary entries of data objects which are represented by * specified nodes. * @param jc jar content from which we are removing files */ public static void removeFileList (JarContent jc, Node[] nodes) { // transform nodes to collection of file objects DataObject curDo = null; for (int i = 0; i < nodes.length; i++) { curDo = (DataObject)nodes[i].getCookie(DataObject.class); if (curDo != null) { // remove primary file object jc.removeFile(curDo.getPrimaryFile()); } } } /** Updates the manifest in given jar content -> it means * that it synchronizes the content of the manifest with other * properties of jar content. More specifically, it regenerates file * list, basic identification, versioning etc., according to the * flags in jar content. */ public static void updateManifest (JarContent jc) { boolean fileList = jc.isManifestFileList(); boolean mainAttr = jc.isMainAttributes(); //System.out.println("File List: " + fileList); // NOI18N //System.out.println("Main Attr: " + mainAttr); // NOI18N Manifest manifest = jc.getManifest(); //System.out.println("Man before update: " + manifest); // NOI18N if (manifest == null) { manifest = new Manifest(); } //System.out.println("Man before main attrs: " + manifest); // NOI18N // update main attributes if (mainAttr) { completeMainAttributes(manifest.getMainAttributes()); } else { removeMainAttributes(manifest.getMainAttributes()); } // update file list //System.out.println("Man before previous files: " + manifest); // NOI18N removeOldEntries(jc); //System.out.println("Man before file list: " + manifest); // NOI18N if (fileList) { generateFileList(jc); } else { removeFileList(jc); } jc.setManifest(manifest); //System.out.println("Man after update: " + manifest); // NOI18N } /** Completes main attributes of the manifest. * Adds version and created-by attributes if they are not present. */ public static void completeMainAttributes (Attributes mainAttr) { // add version if missing if (mainAttr.getValue(Attributes.Name.MANIFEST_VERSION) == null) mainAttr.put(Attributes.Name.MANIFEST_VERSION, MANIFEST_VERSION); // add created-by if missing Attributes.Name cbAttr = new Attributes.Name("Created-By"); // NOI18N if (mainAttr.getValue(cbAttr) == null) { mainAttr.put(cbAttr, "Forte for Java v. 1.0 beta"); // NOI18N } } /** Remove main attributes of the manifest. */ public static void removeMainAttributes (Attributes mainAttr) { mainAttr.remove(Attributes.Name.MANIFEST_VERSION); mainAttr.remove(new Attributes.Name("Created-By")); // NOI18N } /** Generates current list of files of jar content to the manifest * of given jar content. If some file entry already exist, it is * left untouched. */ public static void generateFileList (JarContent jc) { Manifest manifest = jc.getManifest(); if (manifest == null) { return; } FileObject curFo = null; String curName = null; Map manifestEntries = manifest.getEntries(); // go through the files and add manifest entries for (Iterator iter = jc.filteredContent().iterator(); iter.hasNext(); ) { curFo = (FileObject)iter.next(); curName = curFo.getPackageNameExt('/', '.'); // generate entry if not present already if (manifestEntries.get(curName) == null) { // create and put attributes for entry Attributes entryAttr = new Attributes(1); //entryAttr.put(Attributes.Name.MAIN_CLASS, curName); manifestEntries.put(curName, entryAttr); } } } /** Removes all empty per-file entries of the file list */ public static void removeFileList (JarContent jc) { Manifest manifest = jc.getManifest(); if (manifest == null) { return; } FileObject curFo = null; String curName = null; Map manifestEntries = manifest.getEntries(); // go through the files build array of entry names which are candidates // for removal (such entries which name doesn't equal to the name // of any file object in list) for (Iterator iter = jc.filteredContent().iterator(); iter.hasNext(); ) { curFo = (FileObject)iter.next(); curName = curFo.getPackageNameExt('/', '.'); Attributes attrs = (Attributes)manifestEntries.get(curName); if ((attrs != null) && (attrs.size() == 0)) { manifestEntries.remove(curName); } } } /** Removes from manifest all empty per-file entries for files * which are not present in file list. * Other entries will remain untouched. */ private static void removeOldEntries (JarContent jc) { Manifest manifest = jc.getManifest(); if (manifest == null) { return; } FileObject curFo = null; String curName = null; Map manifestEntries = manifest.getEntries(); HashSet candidates = new HashSet(manifestEntries.keySet()); // go through the files build array of entry names which are candidates // for removal (such entries which name doesn't equal to the name // of any file object in list) for (Iterator iter = jc.filteredContent().iterator(); iter.hasNext(); ) { curFo = (FileObject)iter.next(); candidates.remove(curFo.getPackageNameExt('/', '.')); } // go through candidates and remove entries with no attributes for (Iterator iter = candidates.iterator(); iter.hasNext(); ) { curName = (String)iter.next(); Attributes attrs = (Attributes)manifestEntries.get(curName); if ((attrs != null) && (attrs.size() == 0)) { manifestEntries.remove(curName); } } } /** Centers given component relative to packaging view. * Size of the component must be already known */ public static void centerRelativeToPV (Component comp) { Rectangle modeBounds = TopManager.getDefault().getWindowManager().getCurrentWorkspace(). findMode(PackagingView.getPackagingView()).getBounds(); Dimension compSize = comp.getSize(); comp.setLocation( modeBounds.x + (modeBounds.width - compSize.width) / 2, modeBounds.y + (modeBounds.height - compSize.height) / 2 ); } /** Utility method that creates new jar file system with given * root file and adds created file system to the repository. * @param writeable true if file system should be writeable, * false if read-only is enough */ public static FileSystem addJarFSToRepository (File rootFile, boolean writeable) throws IOException, PropertyVetoException { Repository repo = TopManager.getDefault().getRepository(); FileSystem foundFS = getMountedJarFS(rootFile); if (foundFS == null) { JarFileSystem jarFs = new JarFileSystem(); jarFs.setJarFile(rootFile); repo.addFileSystem(jarFs); return jarFs; } return foundFS; } /** @return FileSystem which has given jar file as its root or * null if no such file system could be found in repository */ public static FileSystem getMountedJarFS (File rootFile) { Repository repo = TopManager.getDefault().getRepository(); // PENDING -> checking is not robust, should be done better.. // PENDING - writeable file systems not yet supported FileSystem[] allFS = repo.toArray(); for (int i = 0; i < allFS.length; i++) { if ((allFS[i] instanceof JarFileSystem) && rootFile.equals(((JarFileSystem)allFS[i]).getJarFile())) { return allFS[i]; } } return null; } /** Tries to inspect given node for JarDataObejct cookie * and asks for its jar content. * @return JarContent connected with specified node or null * if no such jar content can be found. */ public static JarContent jarContentFromNode (Node node) { JarDataObject jdo = (JarDataObject)(node.getCookie(JarDataObject.class)); return (jdo != null) ? jdo.getJarContent() : null; } } /* * <<Log>> * 13 Gandalf 1.12 1/25/00 David Simonek Various bugfixes and i18n * 12 Gandalf 1.11 1/16/00 David Simonek i18n * 11 Gandalf 1.10 12/7/99 David Simonek * 10 Gandalf 1.9 11/11/99 David Simonek add to jar action failure * repaired * 9 Gandalf 1.8 11/9/99 David Simonek bugfixes and new mount * jar action * 8 Gandalf 1.7 10/23/99 Ian Formanek NO SEMANTIC CHANGE - Sun * Microsystems copyright in file comment * 7 Gandalf 1.6 10/14/99 David Simonek manifest updating * bugfixes * 6 Gandalf 1.5 10/13/99 David Simonek various bugfixes * concerning primarily manifest * 5 Gandalf 1.4 10/13/99 David Simonek jar content now primary * file, other small changes * 4 Gandalf 1.3 10/10/99 Petr Hamernik console debug messages * removed. * 3 Gandalf 1.2 10/5/99 David Simonek various fixes, only * primary entries now resides in 'chosen content' * 2 Gandalf 1.1 10/4/99 David Simonek * 1 Gandalf 1.0 9/8/99 David Simonek * $ */